

package com.hazelcast.nio.serialization.compatibility;

import com.hazelcast.aggregation.Aggregators;
import com.hazelcast.core.EntryEventType;
import com.hazelcast.internal.serialization.Data;
import com.hazelcast.internal.serialization.impl.HeapData;
import com.hazelcast.internal.serialization.impl.compact.CompactTestUtil;
import com.hazelcast.nio.serialization.Portable;
import com.hazelcast.projection.Projections;
import com.hazelcast.query.Predicates;
import com.hazelcast.query.SampleTestObjects;
import example.serialization.AllFieldsDTO;
import example.serialization.MainDTO;

import java.io.Externalizable;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.CharBuffer;
import java.time.*;
import java.util.*;
import java.util.concurrent.*;

import static java.util.Arrays.asList;

class ReferenceObjects {

    /**
     * PORTABLE IDS
     **/
    static int PORTABLE_FACTORY_ID = 1;
    static int PORTABLE_CLASS_ID = 1;
    static int INNER_PORTABLE_CLASS_ID = 2;

    /**
     * IDENTIFIED DATA SERIALIZABLE IDS
     **/
    static int IDENTIFIED_DATA_SERIALIZABLE_FACTORY_ID = 1;
    static int DATA_SERIALIZABLE_CLASS_ID = 1;

    /**
     * CUSTOM SERIALIZER IDS
     */
    static int CUSTOM_STREAM_SERIALIZABLE_ID = 1;
    static int CUSTOM_BYTE_ARRAY_SERIALIZABLE_ID = 2;

    /**
     * OBJECTS
     */
    static Object aNullObject = null;
    static boolean aBoolean = true;
    static byte aByte = 113;
    static char aChar = 'x';
    static double aDouble = -897543.3678909d;
    static short aShort = -500;
    static float aFloat = 900.5678f;
    static int anInt = 56789;
    static long aLong = -50992225L;
    static String aString;
    static String anSqlString = "this > 5 AND this < 100";
    static UUID aUUID = new UUID(aLong, anInt);
    static String aSmallString = "😊 Hello Приве́т नमस्ते שָׁלוֹם";
    static boolean[] booleans = {true, false, true};
    static byte[] bytes = {112, 4, -1, 4, 112, -35, 43};
    static char[] chars = {'a', 'b', 'c'};
    static double[] doubles = {-897543.3678909d, 11.1d, 22.2d, 33.3d};
    static short[] shorts = {-500, 2, 3};
    static float[] floats = {900.5678f, 1.0f, 2.1f, 3.4f};
    static int[] ints = {56789, 2, 3};
    static long[] longs = {-50992225L, 1231232141L, 2L, 3L};
    static String[] strings = {"Pijamalı hasta, yağız şoföre çabucak güvendi.", "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム", "The quick brown fox jumps over the lazy dog",};
    static Data aData = new HeapData("111313123131313131".getBytes());
    static AnInnerPortable anInnerPortable = new AnInnerPortable(anInt, aFloat);
    static Portable[] portables = {anInnerPortable, anInnerPortable, anInnerPortable};
    static AbstractMap.SimpleEntry aSimpleMapEntry = new AbstractMap.SimpleEntry(aSmallString, anInnerPortable);
    static AbstractMap.SimpleImmutableEntry aSimpleImmutableMapEntry = new AbstractMap.SimpleImmutableEntry(aSmallString, anInnerPortable);
    static CustomStreamSerializable aCustomStreamSerializable = new CustomStreamSerializable(anInt, aFloat);
    static CustomByteArraySerializable aCustomByteArraySerializable = new CustomByteArraySerializable(anInt, aFloat);
    static AnIdentifiedDataSerializable anIdentifiedDataSerializable = new AnIdentifiedDataSerializable(aBoolean, aByte, aChar, aDouble, aShort, aFloat, anInt, aLong, aSmallString, booleans, bytes, chars, doubles, shorts, floats, ints, longs, strings, anInnerPortable, null, aCustomStreamSerializable, aCustomByteArraySerializable, aData);
    static Date aDate;
    static LocalDate aLocalDate;
    static LocalTime aLocalTime;
    static LocalDateTime aLocalDateTime;
    static OffsetDateTime aOffsetDateTime;
    static LocalDate[] localDates;
    static LocalTime[] localTimes;
    static LocalDateTime[] localDateTimes;
    static OffsetDateTime[] offsetDateTimes;
    static BigInteger aBigInteger = new BigInteger("1314432323232411");
    static BigDecimal aBigDecimal = new BigDecimal(31231);
    static BigDecimal[] decimals = {aBigDecimal, aBigDecimal, aBigDecimal};
    static APortable aPortable = new APortable(aBoolean, aByte, aChar, aDouble, aShort, aFloat, anInt, aLong, anSqlString, aBigDecimal, aLocalDate, aLocalTime, aLocalDateTime, aOffsetDateTime, anInnerPortable, booleans, bytes, chars, doubles, shorts, floats, ints, longs, strings, decimals, localDates, localTimes, localDateTimes, offsetDateTimes, portables, anIdentifiedDataSerializable, aCustomStreamSerializable, aCustomByteArraySerializable, aData);
    static Class aClass = BigDecimal.class;
    static Optional<String> aFullOptional = Optional.of("SERIALIZEDSTRING");
    static Optional<String> anEmptyOptional = Optional.empty();
    static Enum anEnum = EntryEventType.ADDED;
    static Serializable serializable = new AJavaSerialiazable(anInt, aFloat);
    static Externalizable externalizable = new AJavaExternalizable(anInt, aFloat);
    static ArrayList nonNullList = new ArrayList(asList(aBoolean, aByte, aChar, aDouble, aShort, aFloat, anInt, aLong, aSmallString, anInnerPortable, booleans, bytes, chars, doubles, shorts, floats, ints, longs, strings, aCustomStreamSerializable, aCustomByteArraySerializable, anIdentifiedDataSerializable, aPortable, aDate, aLocalDate, aLocalTime, aLocalDateTime, aOffsetDateTime, aBigInteger, aBigDecimal, aClass, anEmptyOptional, aFullOptional, anEnum, aSimpleMapEntry, aSimpleImmutableMapEntry, serializable, externalizable));
    static ArrayList arrayList = new ArrayList(asList(aNullObject, nonNullList));
    static LinkedList linkedList = new LinkedList(arrayList);
    static CopyOnWriteArrayList copyOnWriteArrayList = new CopyOnWriteArrayList(arrayList);
    static HashSet hashSet = new HashSet(arrayList);
    static LinkedHashSet linkedHashSet = new LinkedHashSet(arrayList);
    static CopyOnWriteArraySet copyOnWriteArraySet = new CopyOnWriteArraySet(arrayList);
    static ArrayDeque arrayDeque = new ArrayDeque(nonNullList);
    static LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue(nonNullList);
    static LinkedTransferQueue linkedTransferQueue = new LinkedTransferQueue(nonNullList);
    static Comparable<SampleTestObjects.ValueType> aComparable = new SampleTestObjects.ValueType(aSmallString);
    static HashMap hashMap = new HashMap();
    static ConcurrentSkipListMap concurrentSkipListMap = new ConcurrentSkipListMap();
    static ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap(hashMap);
    static LinkedHashMap linkedHashMap = new LinkedHashMap(hashMap);
    static Object[] allTestObjects = {aNullObject, aBoolean, aByte, aChar, aDouble, aShort, aFloat, anInt, aLong, aString, aUUID, anInnerPortable, aSimpleMapEntry, aSimpleImmutableMapEntry, booleans, bytes, chars, doubles, shorts, floats, ints, longs, strings, aCustomStreamSerializable, aCustomByteArraySerializable, anIdentifiedDataSerializable, aPortable, aCompact, aReflectiveCompact, aDate, aLocalDate, aLocalTime, aLocalDateTime, aOffsetDateTime, aBigInteger, aBigDecimal, aClass, aFullOptional, anEnum, serializable, externalizable, arrayList, linkedList, copyOnWriteArrayList, concurrentSkipListMap, concurrentHashMap, linkedHashMap, treeMap, hashSet, treeSet, linkedHashSet, copyOnWriteArraySet, concurrentSkipListSet, arrayDeque, linkedBlockingQueue, arrayBlockingQueue, priorityQueue, priorityBlockingQueue, delayQueue, synchronousQueue, linkedTransferQueue,

            // predicates
            Predicates.alwaysTrue(), Predicates.alwaysFalse(), Predicates.sql(anSqlString), Predicates.equal(aSmallString, aComparable), Predicates.notEqual(aSmallString, aComparable), Predicates.greaterThan(aSmallString, aComparable), Predicates.between(aSmallString, aComparable, aComparable), Predicates.like(aSmallString, aSmallString), Predicates.ilike(aSmallString, aSmallString), Predicates.in(aSmallString, aComparable, aComparable), Predicates.regex(aSmallString, aSmallString), Predicates.partitionPredicate(aComparable, Predicates.greaterThan(aSmallString, aComparable)), Predicates.multiPartitionPredicate(new HashSet<>(Arrays.asList(aComparable)), Predicates.greaterThan(aSmallString, aComparable)), Predicates.and(Predicates.sql(anSqlString), Predicates.equal(aSmallString, aComparable), Predicates.notEqual(aSmallString, aComparable), Predicates.greaterThan(aSmallString, aComparable), Predicates.greaterEqual(aSmallString, aComparable)), Predicates.or(Predicates.sql(anSqlString), Predicates.equal(aSmallString, aComparable), Predicates.notEqual(aSmallString, aComparable), Predicates.greaterThan(aSmallString, aComparable), Predicates.greaterEqual(aSmallString, aComparable)), Predicates.instanceOf(aCustomStreamSerializable.getClass()),

            // Aggregators
            Aggregators.distinct(aSmallString), Aggregators.integerMax(aSmallString), Aggregators.maxBy(aSmallString), Aggregators.comparableMin(aSmallString), Aggregators.minBy(aSmallString), Aggregators.count(aSmallString), Aggregators.numberAvg(aSmallString), Aggregators.integerAvg(aSmallString), Aggregators.longAvg(aSmallString), Aggregators.doubleAvg(aSmallString), Aggregators.bigIntegerAvg(aSmallString), Aggregators.bigDecimalAvg(aSmallString), Aggregators.integerSum(aSmallString), Aggregators.longSum(aSmallString), Aggregators.doubleSum(aSmallString), Aggregators.fixedPointSum(aSmallString), Aggregators.floatingPointSum(aSmallString), Aggregators.bigDecimalSum(aSmallString),

            // projections
            Projections.singleAttribute(aSmallString), Projections.multiAttribute(aSmallString, aSmallString, anSqlString), Projections.identity()};
    static TreeMap treeMap = new TreeMap();
    static TreeSet treeSet = new TreeSet();
    static ConcurrentSkipListSet concurrentSkipListSet = new ConcurrentSkipListSet();
    static ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(5);
    static PriorityBlockingQueue priorityBlockingQueue = new PriorityBlockingQueue();
    static PriorityQueue priorityQueue = new PriorityQueue();
    static DelayQueue delayQueue = new DelayQueue();
    static SynchronousQueue synchronousQueue = new SynchronousQueue();
    static MainDTO aCompact;
    static AllFieldsDTO aReflectiveCompact = CompactTestUtil.createAllFieldsDTO();

    static {
        CharBuffer cb = CharBuffer.allocate(Character.MAX_VALUE);
        for (char c = 0; c < Character.MAX_VALUE; c++) {
            if (!(c >= Character.MIN_SURROGATE && c < (Character.MAX_SURROGATE + 1))) {
                cb.append(c);
            }
        }
        aString = new String(cb.array());
    }

    static {
        Calendar calendar = Calendar.getInstance();
        calendar.set(1990, Calendar.FEBRUARY, 1, 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.ZONE_OFFSET, 0);
        calendar.set(Calendar.DST_OFFSET, 0);
        aDate = calendar.getTime();
        aLocalDate = LocalDate.of(2021, 6, 28);
        aLocalTime = LocalTime.of(11, 22, 41, 123456789);
        aLocalDateTime = LocalDateTime.of(aLocalDate, aLocalTime);
        aOffsetDateTime = OffsetDateTime.of(aLocalDateTime, ZoneOffset.ofHours(18));
        localDates = new LocalDate[]{LocalDate.of(2021, 6, 28), LocalDate.of(1923, 4, 23), LocalDate.of(1938, 11, 10)};
        localTimes = new LocalTime[]{LocalTime.of(9, 5, 10, 123456789), LocalTime.of(18, 30, 55, 567891234), LocalTime.of(15, 44, 39, 192837465)};
        localDateTimes = new LocalDateTime[]{LocalDateTime.of(LocalDate.of(1938, 11, 10), LocalTime.of(9, 5, 10, 123456789)), LocalDateTime.of(LocalDate.of(1923, 4, 23), LocalTime.of(15, 44, 39, 192837465)), LocalDateTime.of(LocalDate.of(2021, 6, 28), LocalTime.of(18, 30, 55, 567891234))};
        offsetDateTimes = new OffsetDateTime[]{OffsetDateTime.of(LocalDate.of(1938, 11, 10), LocalTime.of(9, 5, 10, 123456789), ZoneOffset.ofHours(18)), OffsetDateTime.of(LocalDateTime.of(LocalDate.of(1923, 4, 23), LocalTime.of(15, 44, 39, 192837465)), ZoneOffset.ofHours(5)), OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2021, 6, 28), LocalTime.of(18, 30, 55, 567891234)), ZoneOffset.ofHours(-10))};
    }

    static {
        nonNullList.forEach(e -> {
            if (e != null) {
                if (e instanceof String[] || e instanceof long[] || e instanceof int[] || e instanceof float[] || e instanceof short[] || e instanceof double[] || e instanceof char[] || e instanceof byte[] || e instanceof boolean[]) {
                    // skip these arrays since their equals methods don't work as expected inside the map equals method
                } else {
                    hashMap.put(e.getClass(), e);
                }
            }
        });
    }

    static {
        arrayBlockingQueue.offer(aPortable);
        priorityBlockingQueue.offer(anInt);
        priorityQueue.offer(aSmallString);
    }

    static {
        aCompact = CompactTestUtil.createMainDTO();
        aCompact.localDate = aLocalDate;
        aCompact.localTime = aLocalTime;
        aCompact.localDateTime = aLocalDateTime;
        aCompact.offsetDateTime = aOffsetDateTime;
    }
}
